package com.innerchic.sponsor.builder;

import com.innerchic.sponsor.other.Subject;
import com.innerchic.sponsor.poster.Poster;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 标识一个订阅对象
 * 用于缓存一个订阅方法
 */
public class SubObject implements Comparable<SubObject> {

    /**
     * 当前订阅方法相关
     */
    private final Subject subject;

    /**
     * 执行方法
     */
    private final Method hookMethod;

    /**
     * 关联的类名称
     */
    private final String fromClassName;

    public String getFromClassName() {
        return fromClassName;
    }

    /**
     * 当前类名拼接
     */
    private final String classNames;

    public String getClassNames() {
        return classNames;
    }

    public Method getHookMethod() {
        return hookMethod;
    }

    /**
     * 标识当前方法是否有效
     * true有效
     */
    private boolean isValid = true;

    public SubObject(Subject subject, Method hookMethod, String fromClassName) {
        this.subject = subject;
        this.hookMethod = hookMethod;
        this.fromClassName = fromClassName;
        StringBuilder stringBuilder = new StringBuilder();
        try {
            Class<?>[] parameterTypes = hookMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                stringBuilder.append(parameterType.getName()).append("&");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        classNames = stringBuilder.toString();
    }

    /**
     * 获取Subject
     *
     * @return Subject注解对象
     */
    public Subject getSubject() {
        return subject;
    }

    /**
     * 执行当前订阅
     *
     * @param poster  执行类型
     * @param about   关联的对象
     * @param objects 参数
     */
    public void invoke(Poster poster, Object about, Object... objects) {
        if (poster == null) {
            this.invoke(about, objects);
            return;
        }
        poster.post(() -> this.invoke(about, objects));
    }

    /**
     * 执行当前订阅
     *
     * @param about   关联的对象
     * @param objects 参数
     */
    private void invoke(Object about, Object... objects) {
        if (this.hookMethod == null || subject == null) return;
        if (!subject.isOpen() || !isValid) return;
        try {
            this.hookMethod.invoke(about, objects);
        } catch (IllegalAccessException | InvocationTargetException e) {
            isValid = false;
            e.printStackTrace();
        }
    }

    @Override
    public int compareTo(SubObject o) {
        return o.getSubject().priority();
    }

}
